package org.RSG.Interface;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

import org.RSG.Application.*;

public class ImagePanel extends JPanel implements MouseListener, MouseMotionListener
{
	private static final long serialVersionUID = 1L;
	
	public Point bxy;
	public String pixels[];
	public int width;
	public int height;
	
	private Point oldcoords;
	
	public ImagePanel(int width, int height)
	{
		super(true);
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		this.pixels = new String[(width / 10) * (height / 10)];
		//Reset array
		for(int i = 0; i < this.pixels.length; i++)
		{
			this.pixels[i] = "000000000000";
		}
		this.width = width  / 10;
		this.height = height / 10;
	}
	
	public void paintComponent(Graphics g)
	{
		g.setColor(new Color(255, 255, 255));
		g.fillRect(0, 0, this.getWidth(), this.getHeight());
		//Draw Transparent Background
		g.setColor(new Color(204, 204, 204));
		int j = 0;
		int offset = 0;
		for(j = 0; j < this.getHeight(); j += 5)
		{
			for(int i = 0; i < this.getWidth() + 10; i += 10)
			{
				g.fillRect(i+offset, j, 5, 5);
			}
			if(offset == 5)
			{
				offset = 0;
			} else {
				offset = 5;
			}
		}
		
		for(int i = 0; i < (this.getHeight() / 10); i++)
		{
			for(int z = 0; z < (this.getWidth() / 10); z++)
			{
				//Decipher Tile Data
				int red = Integer.parseInt(this.pixels[this.getTileID(z*10, i*10)].substring(0, 3));
				int green = Integer.parseInt(this.pixels[this.getTileID(z*10, i*10)].substring(3, 6));
				int blue = Integer.parseInt(this.pixels[this.getTileID(z*10, i*10)].substring(6, 9));
				int alpha = Integer.parseInt(this.pixels[this.getTileID(z*10, i*10)].substring(9, 12));
				//Draw Tile Data
				g.setColor(new Color(red, green, blue, alpha));
				g.fillRect(z*10, i*10, 10, 10);
			}
		}
	}
	
	public int getTileID(int x, int y)
	{
		x = (x/10); //How far along the row it is
		y = (y/10); //How far down it is
		int tileid = y * (this.getWidth() / 10);
		tileid += x;

		return tileid;
	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		if(Application.currentTool == 0)
		{
			this.pixels[this.getTileID(e.getX(), e.getY())] = Application.colour;
			this.repaint();
		} else if(Application.currentTool == 1) {
			Application.colour = this.pixels[this.getTileID(e.getX(), e.getY())];
			Application.appdesktop.window.repaint();
		} else if(Application.currentTool == 2) {
			String target = this.pixels[this.getTileID(e.getX(), e.getY())];
			String replacement = Application.colour;
			floodFill(e.getX(), e.getY(), target, replacement);
			this.repaint();
		}
	}
	
	private void floodFill(int x, int y, String target, String replacement)
	{
		if(target != replacement)
		{
			if(!ffPlot(target, replacement, x, y))
			{
				return;
			}
			floodFill(x+10, y, target, replacement);
			floodFill(x-10, y, target, replacement);
			floodFill(x, y+10, target, replacement);
			floodFill(x, y-10, target, replacement);
		}
	}
	
	private boolean ffPlot(String target, String replacement, int x, int y)
	{
		System.out.println("(" + x + "," + y + ")");
		if(this.getTileID(x, y) >= this.pixels.length || this.getTileID(x, y) < 0)
		{
			return false;
		}
		
		if((this.pixels[this.getTileID(x, y)] == target) && ((x / 10) < this.width) && (((y / 10) < this.height)))
		{
			this.pixels[this.getTileID(x, y)] = replacement;
			return true;
		}
		return false;
	}
	
	public void drawLine(int x0, int y0, int x1, int y1) //Implemented from Pseudo-code examples on http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
	{
		boolean steep = Math.abs(y1 - y0) > Math.abs(x1 - x0);
		if(steep)
		{
			//Swap X0, Y0
			int temp = x0;
			x0 = y0;
			y0 = temp;
			//Swap X1, Y1
			temp = x1;
			x1 = y1;
			y1 = temp;
		}
		if(x0 > x1)
		{
			//Swap X0, X1
			int temp = x0;
			x0 = x1;
			x1 = temp;
			//Swap Y0, Y1
			temp = y0;
			y0 = y1;
			y1 = temp;
		}
		int deltax = x1 - x0;
		int deltay = Math.abs(y1 - y0);
		int error = deltax / 2;
		int ystep;
		int y = y0;
		if(y0 < y1)
		{
			ystep = 1;
		} else {
			ystep = -1;
		}
		if(x0 < x1)
		{
			for(int x = x0; x <= x1; x++)
			{
				if(steep) { this.pixels[this.getTileID(y, x)] = Application.colour; } else { this.pixels[this.getTileID(x, y)] = Application.colour; }
		        error = error - deltay;
		        if(error < 0)
		        {
		        	y = y + ystep;
		        	error = error + deltax;
		        }
			}
		} else {
			for(int x = x0; x >= x1; x--)
			{
				if(steep) { this.pixels[this.getTileID(y, x)] = Application.colour; } else { this.pixels[this.getTileID(x, y)] = Application.colour; }
		        error = error - deltay;
		        if(error < 0)
		        {
		        	y = y + ystep;
		        	error = error + deltax;
		        }
			}
		}
	}
	
	@Override
	public void mouseReleased(MouseEvent arg0) {
		this.oldcoords = null;
	}

	@Override
	public void mouseDragged(MouseEvent e) {
		if(Application.currentTool == 0)
		{
			//TODO: Option to allow previous bug(Draw and it will loop back to other side (Remove: X & Y Checks))
			//TODO: Fix Pixel gaps if mouse moved too fast
			/*
			if((this.getTileID(e.getX(), e.getY()) < this.pixels.length) && ((e.getX() / 10) < this.width) && ((e.getY() / 10) < this.height) && ((e.getX() / 10) >= 0) && ((e.getY() / 10) >= 0))
			{
				this.pixels[this.getTileID(e.getX(), e.getY())] = Application.colour;
				this.repaint();
			}
			*/
			if((this.getTileID(e.getX(), e.getY()) < this.pixels.length) && ((e.getX() / 10) < this.width) && ((e.getY() / 10) < this.height) && ((e.getX() / 10) >= 0) && ((e.getY() / 10) >= 0))
			{
				if(this.oldcoords == null)
				{
					this.pixels[this.getTileID(e.getX(), e.getY())] = Application.colour;
				} else {
					this.drawLine(this.oldcoords.x, this.oldcoords.y, e.getX(), e.getY());
				}
			}
			this.oldcoords = new Point(e.getX(), e.getY());
			this.repaint();
		}
	}

	@Override
	public void mouseMoved(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}